// SPDX-FileCopyrightText: 2025 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using Nethermind.Core;
using Nethermind.Core.Extensions;
using Nethermind.Core.Test.Builders;
using Nethermind.Facade.Eth.RpcTransaction;
using Nethermind.Optimism.Rpc;
using Nethermind.Serialization.Rlp;
using NSubstitute;
using NUnit.Framework;

namespace Nethermind.Optimism.Test;

public class OptimismCostHelperTests
{
    [SetUp]
    public void Setup()
    {
        TransactionForRpc.RegisterTransactionType<DepositTransactionForRpc>();
        TxDecoder.Instance.RegisterDecoder(new OptimismTxDecoder<Transaction>());
        TxDecoder.Instance.RegisterDecoder(new OptimismLegacyTxDecoder());
    }

    // Taken from Jovian alpha devnet
    private static IEnumerable<TestCaseData<Func<Block>>> DaFootprintTestCases()
    {
        yield return new(
            () => Rlp.Decode<Block>(Bytes.FromHexString("f9038af90275a02877b2266e1289b448dd45149b03f948a43c5549e4afdd61d10008dbdd839714a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a084b8e1cbd2b4d12ccbe326a8cc76147bade47c03e0a303d975debdba6649c8b8a065f0c9e84ef06aef7ebbc695c789e07136cc9dd9394c7c2dc0dc7a813350a4a4a0a937269931d3b4de64b91cd07c3d0d2af0f392c219a975877836b23152986caab901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080830948a1840393870082b48a84690e77f69101000000fa000000060000000000000000a0e5b3cf85d39b4253b039b9c7078b7f8a106383340d6bee4968d09b349931714b880000000000000000840bbf437ba007e4ba57a118eb434e47a55ef1fafa1e809bf6eb9aa56e8e027542db1b2150bc8080a081040b2fcc3753cbdf7d4d8f5375f294400ed1024603cfaced27c077072e019ea0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f9010db9010a7ef90106a0f53166e2aa01da020685f0cad891915e9d170ed5660d31fa32654ec566bfea5994deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8b23db6be2b00000558000c3c9d000000000000000400000000690e77a4000000000092371500000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001b1bf0a4b07d08b24382f0c0375a493879ff207e15df84abc5ee70261d962e9ac0000000000000000000000001fa33f4830c6939a7e48550c0c2b6b779293a3e305f5e10000000000000001f40190c0c0"))
        )
        { TestName = "Block #608417, no non-deposit txs" };

        yield return new(
            () => Rlp.Decode<Block>(Bytes.FromHexString("f90400f90278a043b245d5a45f3c8a47f4708535dff1569ab4900a0141e9762c27980d11dde5e1a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0d26432a00e0362a3905ca57fb967b649a865dd56bc57885097743162b7adf96ca0b6d7f2049b1d82cb5f3189fb3fc64e0fd37029c0e30ca1f9d130efe5089b1f0ea094b34c410fff6460c21d495dd945214d28a712e0f7e23e6ba323679eb6d6568cb901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080830948a3840393870083019f3084690e77fa9101000000fa000000060000000000000000a0a20f72a960e203f644c258f6471ffc187dc94d70b10304039915a18fd2163cd3880000000000000000840ba777a5a007e4ba57a118eb434e47a55ef1fafa1e809bf6eb9aa56e8e027542db1b2150bc829c4080a0800f146027284dae46a5a6cf14a9120084791267e67fe088dea7456a93d14a4ba0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f90180b9010a7ef90106a00b2bd82bd3369b88c7e3c402acb0f7ed79e9fc00035b34417409ca736d7a7cc494deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8b23db6be2b00000558000c3c9d000000000000000000000000690e77b000000000009237160000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000118d0bf5ef2941afc565c5c8c1dcaf4f3c3dfd3bcbb30e4ed7763bd0c6b21055e0000000000000000000000001fa33f4830c6939a7e48550c0c2b6b779293a3e305f5e10000000000000001f40190b87102f86e84190a37a680843b9aca0084474e1447830f4240808093600661000d60003960066000f361beef600055c080a0c4b911fe7306728641bdf90b398bc596d01c4677486c6ce5cb862bb145b3e251a03b31f488019dae760ab73708d41c8da8e2735e04b3d2fbedd727fcf4ae37cd8cc0c0"))
        )
        { TestName = "Block #608419" };

        yield return new(
            () => Rlp.Decode<Block>(Bytes.FromHexString("f90463f90278a0d139f43e1ef1dbd1dc158ece6dcee7ec4b5a0e4ee60140d3c96c5cc1d3508069a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a0835d1756d995d0b561ec2fdc109112d700dd57d920023abb5a5efbc7e63ac5cba030f6c21d4a1a7b67a1283eefc070523de4af12004abab250a0a1222229f9eac1a0bd1344a3af8432513780576c8d7a39871fd9c4d88cf53c4e7b98c10951bcbf85b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080830948a4840393870083018dc084690e77fc9101000000fa000000060000000000000000a0a20f72a960e203f644c258f6471ffc187dc94d70b10304039915a18fd2163cd3880000000000000000840b9ba90ca007e4ba57a118eb434e47a55ef1fafa1e809bf6eb9aa56e8e027542db1b2150bc82d7a080a0800f146027284dae46a5a6cf14a9120084791267e67fe088dea7456a93d14a4ba0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f901e3b9010a7ef90106a0d8e29b7d16f95249d13aac79b119ce6726bd2c8b05ee70323ada20b86d7441ff94deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8b23db6be2b00000558000c3c9d000000000000000100000000690e77b000000000009237160000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000118d0bf5ef2941afc565c5c8c1dcaf4f3c3dfd3bcbb30e4ed7763bd0c6b21055e0000000000000000000000001fa33f4830c6939a7e48550c0c2b6b779293a3e305f5e10000000000000001f40190b8d404f8d184190a37a601843b9aca0084474241a5830124f89450c96a7e536f89417891ac992b248d2e883178408080c0f860f85e84190a37a694b56379fb2a6cf01281b7f749b3aa651d9098f0dd0280a058294c13e08193e5141709e453fdccee7c4b2d2a35c88060b4d60d61e2b1100ea0731c9bb8d3bacca7d60c1393c73b667a365bc95986245325b728ad2e3590bc1101a0bcbf7bdf67b5ea32a8e6a6ccbd6878c6d8c71d90fe1edf2da3bce16edc1129caa03329ec62005b049465b78818084a0beb7da56800892e5a508ed2f1bb662e09cdc0c0"))
        )
        { TestName = "Block #608420" };

        yield return new(
            () => Rlp.Decode<Block>(Bytes.FromHexString("f90c06f90279a0347f8f0939dd3332436fb617a37ce7cecaa31dc14335181104587fd44da77200a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944200000000000000000000000000000000000011a038d7d1a9432f41681a1b122e5fae9f511cf1de739bc5875f2c61a53560dacf97a07903266fe205f14c8222192dc8a816f6c626acc047133e818a22d3d65b4aa55ea0c8e7da2d8bfb098323abac42f1f3550dca8b983cdf70bdcc2cde8f83f5aeffd6b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080830948a58403938700830245fc84690e77fe9101000000fa000000060000000000000000a0a20f72a960e203f644c258f6471ffc187dc94d70b10304039915a18fd2163cd3880000000000000000840b8fe50ea007e4ba57a118eb434e47a55ef1fafa1e809bf6eb9aa56e8e027542db1b2150bc830b0f4080a0800f146027284dae46a5a6cf14a9120084791267e67fe088dea7456a93d14a4ba0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f90985b9010a7ef90106a05099eb0104027af3672c4f59bcefdf80a951453ecc705aa829be99948b4637f294deaddeaddeaddeaddeaddeaddeaddeaddead00019442000000000000000000000000000000000000158080830f424080b8b23db6be2b00000558000c3c9d000000000000000200000000690e77b000000000009237160000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000118d0bf5ef2941afc565c5c8c1dcaf4f3c3dfd3bcbb30e4ed7763bd0c6b21055e0000000000000000000000001fa33f4830c6939a7e48550c0c2b6b779293a3e305f5e10000000000000001f40190b9087502f9087184190a37a603843b9aca00844736730c8301955194000000000000000000000000000000000000000480b908007aa771b811222b967cbdf61cd4cab7f29b6afd39d5d5f706a28f24087573ba597ae05ba80a7825e05fa1305b5099b974daf0402f41f2067ad63028555fdad76ec1080651374ae5968c37ce16b0e96bad54c479f88329d3075f21fe51a73bd585aa8cb23938894e5c77f40e1b99de67e3a7a933e6a385cb1d5d9395707dc0549394533d3e581f47cea1f28a2e645dbefd300e2011a30b6f99c704ac919d4739f9dba32ee0576dd0966541dbada0421bdacf4de335dd42511e78f817159a10626f297d3315b097f0f48789ae5450927cdbbf15350f94fe82518ed5979aca29b858cdd285eb5736fdaa02079cf9c55b24492088fbbb0df30fbcd1da98a9473b70032d5864ff9f5a4aa70c329aa17171f007e27d08fb583d894ebefbb84551bd6e6094da77a52f2f3fb0494fa58e1a5583d100a55859cbe0a39f40200c913a46e0f789ccbdd7ec139e79f273a3071a85606606075f53038de1cde2a8fb018fde72c0c319e4ae0486fefcb6f2a4f3c5363304a5236d82f515c8c4c35142dab29b3bdc020b39b9aa9d101bd84d1620b3228f977fb1ff5cec2fc9022f3beb760565eb35919bac1e17b530499c05fa350e99b691880169f8854051cd0bd1cc4802613527d09ed1665cd7bc0335ead7e080357f7b97fe4a0c098a62d7ec634f8f4fbfca4b9778369c12fa734989b85332d519a50f673db4fe1792d6cf6252a5a60c91c994c1be11a53a7a9dc93fbfe4fb0c32921f55e158f267b00fd9ab7186d8028fca6df858fa015dd5b10ed5c0f34b5a604e82ff0ee6cf2ec1d4613b8d5ca22405a4c1e0b855e31b07c1e3b6d5bb11ec68a8ce39d8e99c61512fc7586b9dc748b7e8902eecbb44cb9668d8c4a2bb5fd9c6d1f8996aa903760926e3f6ac97f08dd9099dcb6db2b0cfec6b2b541c61b401942c42bdbb86d55ff2c069e1d8d0cfddc88cf95cb85e92f621d9c3a932daa777de8d70ddf096cabe95981396890ada4882bf0edc1666c9dc6486ca7d92a05f1e4be604c6cbd298656a8324656dc717c64d36f646b1733dbfe1741190a1dbc5aa6cff55db7a0699e084be3878e13f4408116bfa8c9fca5bda85b8b4ef04e52784cf385701b3c62398a71ca546789efbbbe5ff6f1ea2a13e8d158bf98769fe648c04f43ce472a4e027b7d3c525ff859a6b61fc63045672a090036d47fbd91e19886bb1999ae50c88ac240cc4641d3ad8878cd0c2b68860c11e863c8e0ffcd08384159eb1ce470d735a90ee09e22f265e288687beabe5d66a1d4219a079482fac4dd1b6e1c87b974c254130cd16f354cdd08d1f0bd1c31e8b53492d3d2856daabc64ffe048556b589a6bc7ad374a4ff9b93bfbf583c619999c861ec5eb62fcbb37519653cb641ea1cd7386e57981e3929ba73ad7ef7d2c52da130d7bd1123f899dbd6e8a5ee54def127a4ef66287f4ca0d8ebae807a5f347d8bf5e67b723f76e165fca9df2e91bbe3cc08822819c6781d4796464053181296e96acb100ab4ff3a0a4c731eb2b3e7c47f7b3580d0e451e1f0e7ca78b7bad43189967e9edefcb08ec4ed07eb0227653f926924d0ee45befa18ba5733ac3b8db632f80f775880be257d39b83c2184f006909beb707e6c7070ff04bc5b684be13f6b48bb3c1681c6ee9f17a2674f92551381c929dbfc4e7587cb259637dcdad85ee150a6a282a3e8be7f0ef684f38b2fe0d316233c99ee886940dfe85d872e92224159560865b6ee043ba5e73f20f23382ccafdd039dd46e79aaaa20913ae9a90bc87489e7e88e938a96ea685bb80668fce0549df4af6ef5a166101926cdbbb8ebb6e1d972b58989e36b6597ae047d900b9f958ac26fe12d8d18c2d2b0f6778349f723068499e6bb31c39aadab7e318babb7187c7b851fbfaff0b8bae72044e69c0a9cf52771d0d0951420127c248182792473b125a04df57ea3d017dd9ac573ba5a1085b34239d8fa993ef5292f3e66c7ef7be2048d69ea8f318955da52256d406f3280f3703488d343a248fcc1024225c0f3a93369443b693e6dcffe02b7b02d52e5a0c2222ff3290c00962669ebb5e9b801be0c021added34b4d981a5e4305a4bcb206089ffe5077bd722859f1ab23e2b660540f8b4bb086c1b9b2b7307fedd7f4c01184342469d863c849a652510bce7d2a3edba048bb9dccd0db1c74e6b95a079ae96222bce0ac32b6eb7ba0910b17d7587d89c624827969eab8f3a6e66ae81d8420bdb56e257e2b4013e57ac5552046be9fddd6c32f04ef6cb3a553dba90fc4b00a999c72c4c09fc0688b790ad4ee6c8fa15919ec67ceeab194d1c48a28c618b0bce4a521bba1b258d5be368f3c69f8f037e7d1bb4066f92272a2b0583afada2932e7a7b112d40176c33c3ed397d14438888ef858bca5b894ffef770cd60762618caa6853256267416848eaf3b2aba2caa89bc3928bbbe8923e83795c41e9ce4893f04a669fdeb71e2e5de1c16525547abc7a3d8644cd9de00f7f1a3fa120016720c523104dd659bb84b6849a0371c3fa6b5d651cb4d1114fcc7a7a91535322b9ba91c0bad0eef60dcadaded15bb92d179dd7fc80b1a05d457b4ca5d1be0a5c9536d2f562a89fc64fa63025687e70d95461663bfbbe6761b1fc9fbae2c29bda1eccb706d16177e070510254080f63c985fecf0f63eb9c18382d8ac36ffae949ac5eec8a6a26178c28ed0699a542a68e222133078b15179448df9a86347e2a64e752bddee9047c3d251acc5ee8be0184d8e1d57e15dfbff209b76fb261de2df3d2975f7c50152e84bd5710bbd3323e0fcfac2b5f20229a282ca1811ade19ab6b6cf29ae348b27040d946a0509b8bf02dfff98ff6706802c7b461c93e524f0ec07950e0e6cf19ceed24cc8ac2de191146dc344985dd5e09150a5bfc080a0be7b84dd6b461c8f1d630f54c6c05d961589ccf036455fc082e8896132c24e1da0247fad718515d3d8cbffa20c4bf23c997681fbed69b2df3ff346ea532c6adc86c0c0"))
        )
        { TestName = "Block #608421" };
    }

    [TestCaseSource(nameof(DaFootprintTestCases))]
    public void ComputeDaFootprint(Func<Block> blockFactory)
    {
        Address l1BlockAddr = Build.An.Address.TestObject;
        var specHelper = Substitute.For<IOptimismSpecHelper>();

        Block block = blockFactory();
        var helper = new OptimismCostHelper(specHelper, l1BlockAddr);

        Assert.That((long)helper.ComputeDaFootprint(block), Is.EqualTo(block.BlobGasUsed));
    }
}
